﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FizzBuzzLib
{
    public class FizzBuzz
    {
        /// <summary>
        /// A reusable implementation of the classic FizzBuzz algorithm 
        /// <see cref="http://www.codinghorror.com/blog/2007/02/why-cant-programmers-program.html"/>
        /// </summary>
        /// <param name="start">The lower bound of the range of integer values.</param>
        /// <param name="count">The size of the range of integer value.s</param>
        /// <param name="fizz">When value is divisible by 3 but not by 5, result is this string. Default is "Fizz".</param>
        /// <param name="buzz">When value is divisible by 5 but not by 3, result is this string. Default is "Buzz".</param>
        /// <param name="fizzBuzz">When value is divisible by 5 and by 3, result is this string. Default is "FizzBuzz".</param>
        /// <returns>A sequence of strings</returns>
        public static IEnumerable<string> Results(int start,
                                                  int count,
                                                  string fizz = "Fizz",
                                                  string buzz = "Buzz",
                                                  string fizzBuzz = "FizzBuzz")
        {
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", "Must be non-negative");
            if (fizz == null)
                throw new ArgumentNullException("fizz");
            if (buzz == null)
                throw new ArgumentNullException("buzz");
            if (fizzBuzz == null)
                throw new ArgumentNullException("fizzBuzz");

            for (int value = start; value != checked(start + count); ++value)
            {
                if ((value % 3 == 0) && (value % 5 == 0))
                    yield return fizzBuzz;
                else if (value % 3 == 0)
                    yield return fizz;
                else if (value % 5 == 0)
                    yield return buzz;
                else
                    yield return value.ToString();
            }
        }
    }
}
